/*
 * surface.h
 *
 *  Created on: Dec 9, 2008
 *      Author: yangcheng
 */

#ifndef SURFACE_H_
#define SURFACE_H_
#include<GL/glut.h>
#include<cmath>
#include"glm.h"
#include<assert.h>
using std::sqrt;
struct Triangle {
	GLuint verts[3];
	Triangle() {
	}
	Triangle(GLuint v1, GLuint v2, GLuint v3) {
		verts[0] = v1;
		verts[1] = v2;
		verts[2] = v3;
	}
};

struct Vertex {
	GLfloat x, y, z;
	GLboolean newpoint; //odd are newpoint
	Vertex *averaged;
	Vertex *next;
	Vertex() {
		newpoint=GL_TRUE;
		next = NULL;
		averaged=NULL;
	}
	Vertex(GLfloat _x, GLfloat _y, GLfloat _z) :
		x(_x), y(_y), z(_z) {
		next = NULL;
		newpoint=GL_TRUE;
		averaged=NULL;
	}
};
struct Face;//forward delaration
struct Edge {
	Vertex* head;
	Vertex* tail;
	Edge* next;
	Edge* prev;
	Edge* twin;
	Face *left;
	Face* right;

	Edge() {
		head = tail = NULL;
		twin = next = prev = NULL;
		left = right = NULL;
	}
};

struct Face {
	Edge* edges;
	Vertex* normal;
	Face* next; //linked list
	Face() {
		edges = NULL;
		next = NULL;
		normal = NULL;
	}
};
struct WingedEdge {
	Face* faces;
	Vertex* vertices;
};

struct Model {
	GLuint numVertices;
	GLuint numFaces;
	Vertex* position;
};

WingedEdge* readGLM(GLMmodel *model);
GLvoid flatWe(WingedEdge* we);
GLvoid wireWe(WingedEdge* we);
GLvoid generateNormals(WingedEdge* we);
GLvoid subdivide(WingedEdge* we);
GLvoid subDivision(WingedEdge *we);
GLvoid generateMid(Face *face);
GLvoid connectEdge(Face *face);
GLvoid generateOdd(WingedEdge *we);
GLvoid maskOdd(WingedEdge *we);
GLvoid maskEven(WingedEdge *we);
inline Vertex* crossProduct(const Vertex& u, const Vertex& v) {
	return new Vertex(u.y * v.z - u.z * v.y, u.z * v.x - u.x * v.z, u.x * v.y
			- u.y * v.x);
}
inline Vertex* midpoint(const Vertex& u, const Vertex& v) {
	return new Vertex((u.x + v.x) / 2, (u.y + v.y) / 2, (u.z + v.z) / 2);
}

inline Vertex* midpoint(Vertex* u, Vertex* v) {
	return new Vertex((u->x + v->x) / 2, (u->y + v->y) / 2, (u->z + v->z) / 2);
}
inline GLfloat dotProduct(const Vertex& u, const Vertex& v) {
	return u.x * v.x + u.y * v.y + u.z * v.z;
}
inline GLvoid normalize(Vertex& v) {
	GLfloat n = sqrt(dotProduct(v, v));
	v.x = v.x / n;
	v.y = v.y / n;
	v.z = v.z / n;
}

inline GLfloat beta(int n){
float x=3.0+2.0*cos(2.0*M_PI/n);
	return (0.625- x*x/64.0);

}
#endif /* SURFACE_H_ */
